#include <cstdio>

typedef long long ll;
const int N = 1e5 + 5;

int n, m, p;
int val[N << 2], a[N], add[N << 2], mul[N << 2];

inline void pushup(int x) { val[x] = (val[x << 1] + val[x << 1 | 1]) % p; }

inline void pushdown(int x, int l, int r) {
  static int ls, rs, mid;
  if (add[x] == 0 && mul[x] == 1) return;
  ls = x << 1, rs = x << 1 | 1, mid = (l + r) >> 1;
  val[ls] = (1ll * val[ls] * mul[x] % p + 1ll * (mid - l + 1) * add[x] % p) % p;
  val[rs] = (1ll * val[rs] * mul[x] % p + 1ll * (r - mid) * add[x] % p) % p;
  add[ls] = (1ll * add[ls] * mul[x] + add[x]) % p;
  add[rs] = (1ll * add[rs] * mul[x] + add[x]) % p;
  mul[ls] = 1ll * mul[ls] * mul[x] % p;
  mul[rs] = 1ll * mul[rs] * mul[x] % p;
  add[x] = 0, mul[x] = 1;
}

void build(int x, int l, int r) {
  add[x] = 0, mul[x] = 1;
  if (l == r) {
    val[x] = a[l];
    return;
  }
  int mid = (l + r) >> 1;
  build(x << 1, l, mid);
  build(x << 1 | 1, mid + 1, r);
  pushup(x);
}

void Add(int x, int l, int r, int L, int R, int v) {
  if (L <= l && r <= R) {
    (add[x] += v) %= p;
    (val[x] += 1ll * (r - l + 1) * v % p) %= p;
    return;
  }
  int mid = (l + r) >> 1;
  pushdown(x, l, r);
  if (L <= mid) Add(x << 1, l, mid, L, R, v);
  if (mid < R) Add(x << 1 | 1, mid + 1, r, L, R, v);
  pushup(x);
}

void Multiply(int x, int l, int r, int L, int R, int v) {
  if (L <= l && r <= R) {
    add[x] = (long long)v * add[x] % p;
    mul[x] = (long long)v * mul[x] % p;
    val[x] = (long long)v * val[x] % p;
    return;
  }
  int mid = (l + r) >> 1;
  pushdown(x, l, r);
  if (L <= mid) Multiply(x << 1, l, mid, L, R, v);
  if (mid < R) Multiply(x << 1 | 1, mid + 1, r, L, R, v);
  pushup(x);
}

int query(int x, int l, int r, int L, int R) {
  if (L <= l && r <= R) {
    return val[x];
  }
  int mid = (l + r) >> 1;
  pushdown(x, l, r);
  ll sum = 0;
  if (L <= mid) sum += query(x << 1, l, mid, L, R);
  if (mid < R) sum += query(x << 1 | 1, mid + 1, r, L, R);
  return sum % p;
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("testdata.in", "r", stdin);
  freopen("testdata.out", "w", stdout);
#endif
#ifndef LOCAL
  freopen("SegmentTree2.in", "r", stdin);
  freopen("SegmentTree2.out", "w", stdout);
#endif
#endif

  scanf("%d%d%d", &n, &m, &p);
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &a[i]);
    a[i] %= p;
  }
  build(1, 1, n);
  int opt, x, y, k;
  while (m--) {
    scanf("%d%d%d", &opt, &x, &y);
    if (opt == 3) {
      printf("%d\n", query(1, 1, n, x, y));
    } else {
      scanf("%d", &k);
      if (opt == 1) {
        Multiply(1, 1, n, x, y, k);
      } else {
        Add(1, 1, n, x, y, k);
      }
    }
  }
  return 0;
}